package com.crm.redis.mapper;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.crm.redis.RedisTtlConfig;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.StringRedisTemplate;

import java.util.Collection;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Slf4j
public class ValueRMapper {

    /**
     * 获取redis中的缓存，不更新过期时间
     *
     * @param redisTemplate
     * @param key
     * @return
     */
    public static String getRedisString(StringRedisTemplate redisTemplate, String key) {
        if (StringUtils.isBlank(key)) {
            return null;
        }
        try {
            return redisTemplate.opsForValue().get(key);
        } catch (Exception e) {
            log.error("R_ValueRedisMapper getRedisString ERROR:", e);
            log.error("Data:" + key);
            throw e;
        }
    }

    /**
     * 获取redis中的缓存，手动更新过期时间
     *
     * @param redisTemplate
     * @param key
     * @param timeout
     * @param timeunit
     * @return
     */
    public static String getRedisString(StringRedisTemplate redisTemplate, String key, long timeout, TimeUnit timeunit) {
        if (StringUtils.isBlank(key)) {
            return null;
        } else {
            try {
                String s = redisTemplate.opsForValue().get(key);
                setRedisTimeout(redisTemplate, key, timeout, timeunit);
                return s;
            } catch (Exception e) {
                log.error("R_ValueRedisMapper getRedisString set timeout by hand ERROR:", e);
                log.error("Data:" + key);
                throw e;
            }
        }
    }

    /**
     * 从redis中获取object，不更新过期时间
     *
     * @param redisTemplate
     * @param key
     * @param clazz
     * @param <T>
     * @return
     */
    public static <T> T getRedisObject(StringRedisTemplate redisTemplate, String key, Class<T> clazz) {
        if (StringUtils.isBlank(key)) {
            return null;
        }
        try {
            String objectString = redisTemplate.opsForValue().get(key);
            if (objectString == null) {
                return null;
            }
            return (T) JSON.parseObject(objectString, clazz);
        } catch (Exception e) {
            log.error("R_ValueRedisMapper getRedisObject ERROR:", e);
            log.error("Data:" + key);
            throw e;
        }
    }

    /**
     * 从redis中获取List
     *
     * @param redisTemplate
     * @param key
     * @param clazz
     * @param <T>
     * @return
     */
    public static <T> List<T> getRedisObjectList(StringRedisTemplate redisTemplate, String key, Class<T> clazz) {
        if (StringUtils.isBlank(key)) {
            return null;
        }
        try {
            String objectString = redisTemplate.opsForValue().get(key);
            if (objectString == null) {
                return null;
            }
            return JSONArray.parseArray(objectString, clazz);
        } catch (Exception e) {
            log.error("R_ValueRedisMapper getRedisObject ERROR:", e);
            log.error("Data:" + key);
            throw e;
        }
    }

    /**
     * 为一个缓存赋值，但是不给过期时间
     *
     * @param redisTemplate
     * @param key
     * @param value
     * @return
     */
    public static boolean setRedisString(StringRedisTemplate redisTemplate, String key, String value) {
        if (StringUtils.isBlank(key) || value == null) {
            return false;
        }
        try {
            redisTemplate.opsForValue().set(key, value);
            return true;
        } catch (Exception e) {
            log.error("R_ValueRedisMapper setRedisString ERROR:", e);
            log.error("Data:" + key);
            throw e;
        }
    }

    /**
     * 为一个缓存赋值，手动录入过期时间
     *
     * @param redisTemplate
     * @param key
     * @param value
     * @param time          过期时间的数值
     * @param timeunit      过期时间的单位
     * @return
     */
    public static boolean setRedisString(StringRedisTemplate redisTemplate, String key, String value, long time, TimeUnit timeunit) {
        if (StringUtils.isBlank(key) || value == null) {
            return false;
        }
        try {
            redisTemplate.opsForValue().set(key, value, time, timeunit);
            return true;
        } catch (Exception e) {
            log.error("R_ValueRedisMapper setRedisString set timeout by hand ERROR:", e);
            log.error("Data:" + key);
            throw e;
        }
    }

    /**
     * 为一个缓存赋值，手动录入过期时间
     *
     * @param redisTemplate
     * @param key
     * @param value
     * @param redisTtlConfig 过期时间设置
     * @return
     */
    public static boolean setRedisString(StringRedisTemplate redisTemplate, String key, String value, RedisTtlConfig redisTtlConfig) {
        if (StringUtils.isBlank(key) || value == null) {
            return false;
        }
        try {
            Long time = redisTtlConfig.getTime();
            TimeUnit timeUnit = redisTtlConfig.getTimeUnit();
            redisTemplate.opsForValue().set(key, value, time, timeUnit);
            return true;
        } catch (Exception e) {
            log.error("R_ValueRedisMapper setRedisString set timeout by hand ERROR:", e);
            log.error("Data:" + key);
            throw e;
        }
    }

    /**
     * 为缓存赋值对象或集合，会直接转换为json字符串
     *
     * @param redisTemplate
     * @param key
     * @param value         可传入对象或集合
     * @return
     */
    public static boolean setRedisObject(StringRedisTemplate redisTemplate, String key, Object value) {
        if (StringUtils.isBlank(key) || value == null) {
            return false;
        }
        try {
            redisTemplate.opsForValue().set(key, JSON.toJSONString(value));
            return true;
        } catch (Exception e) {
            log.error("R_ValueRedisMapper setRedisObject ERROR:", e);
            log.error("Data:" + key);
            throw e;
        }
    }


    /**
     * 为缓存赋值对象或集合，会直接转换为json字符串, 并设置偏移量
     *
     * @param redisTemplate
     * @param key
     * @param value         可传入对象或集合
     * @param offset         偏移量
     * @return
     */
    public static boolean setRange(StringRedisTemplate redisTemplate, String key, Object value, long offset) {
        if (StringUtils.isBlank(key) || value == null) {
            return false;
        }
        try {
            redisTemplate.opsForValue().set(key, JSON.toJSONString(value), offset);
            return true;
        } catch (Exception e) {
            log.error("R_ValueRedisMapper setRange ERROR:", e);
            log.error("Data:" + key);
            throw e;
        }
    }

    /**
     * 为缓存赋值对象执行加固定值操作
     *
     * @param redisTemplate
     * @param key
     * @param value         要加/减的数字
     * @return
     */
    public static boolean incrementValue(StringRedisTemplate redisTemplate, String key, int value) {
        if (StringUtils.isBlank(key) || value == 0) {
            return false;
        }
        try {
            redisTemplate.opsForValue().increment(key, value);
            return true;
        } catch (Exception e) {
            log.error("R_ValueRedisMapper setRedisObject ERROR:", e);
            log.error("Data:" + key);
            throw e;
        }
    }

    /**
     * 为缓存赋值对象执行加固定值操作,同时添加过期时间
     *
     * @param redisTemplate
     * @param key
     * @param value
     * @param time
     * @param timeunit
     * @return
     */
    public static boolean incrementValue(StringRedisTemplate redisTemplate, String key, int value, long time, TimeUnit timeunit) {
        if (StringUtils.isBlank(key) || value == 0) {
            return false;
        }
        try {
            redisTemplate.opsForValue().increment(key, value);
            redisTemplate.expire(key, time, timeunit);
            return true;
        } catch (Exception e) {
            log.error("R_ValueRedisMapper setRedisObject ERROR:", e);
            log.error("Data:" + key);
            throw e;
        }
    }

    /**
     * *判断对应的key是否存在
     *
     * @param redisTemplate
     * @param key
     * @return
     */
    public static Boolean hasKey(StringRedisTemplate redisTemplate, String key) {
        Boolean result = false;
        if (!StringUtils.isBlank(key)) {
            result = redisTemplate.hasKey(key);
        }
        return result;
    }

    /**
     * 为缓存赋值对象，会直接转换为json字符串
     * 且可以手动设置过期时间
     *
     * @param redisTemplate
     * @param key
     * @param value
     * @return
     */
    public static boolean setRedisObject(StringRedisTemplate redisTemplate, String key, Object value, long time, TimeUnit timeunit) {
        if (StringUtils.isBlank(key) || value == null) {
            return false;
        }
        try {
            redisTemplate.opsForValue().set(key, JSON.toJSONString(value), time, timeunit);
            return true;
        } catch (Exception e) {
            log.error("R_ValueRedisMapper setRedisObject set timeout by hand ERROR:", e);
            log.error("Data:" + key);
            throw e;
        }
    }

    /**
     * 为缓存赋值对象，会直接转换为json字符串
     * 且可以手动设置过期时间
     *
     * @param redisTemplate
     * @param key
     * @param value
     * @return
     */
    public static boolean setRedisObject(StringRedisTemplate redisTemplate, String key, Object value, RedisTtlConfig redisTtlConfig) {
        if (StringUtils.isBlank(key) || value == null) {
            return false;
        }
        try {
            Long time = redisTtlConfig.getTime();
            TimeUnit timeUnit = redisTtlConfig.getTimeUnit();
            redisTemplate.opsForValue().set(key, JSON.toJSONString(value), time, timeUnit);
            return true;
        } catch (Exception e) {
            log.error("R_ValueRedisMapper setRedisObject set timeout by hand ERROR:", e);
            log.error("Data:" + key);
            throw e;
        }
    }

    /**
     * 手动设置redis 过期时间
     *
     * @param redisTemplate
     * @param key
     * @param timeout
     * @param timeunit
     * @return
     */
    public static boolean setRedisTimeout(StringRedisTemplate redisTemplate, String key, long timeout, TimeUnit timeunit) {
        if (StringUtils.isBlank(key)) {
            return false;
        }
        try {
            if (timeout == 0) {
                redisTemplate.delete(key);
            } else {
                redisTemplate.expire(key, timeout, timeunit);
            }
            return true;
        } catch (Exception e) {
            log.error("R_ValueRedisMapper setRedisTimeout ERROR:", e);
            log.error("Data:" + key);
            throw e;
        }
    }

    /**
     * 根据key值删除redis缓存
     *
     * @param redisTemplate
     * @param key
     * @return
     */
    public static boolean delRedis(StringRedisTemplate redisTemplate, String key) {
        if (StringUtils.isBlank(key)) {
            return false;
        } else {
            try {
                redisTemplate.delete(key);
                return true;
            } catch (Exception e) {
                log.error("R_ValueRedisMapper delRedis ERROR:", e);
                log.error("Data:" + key);
                throw e;
            }
        }
    }

    /**
     * 根据redis key值集合删除redis缓存
     *
     * @param redisTemplate
     * @param keyCollection key值集合
     * @return
     */
    public static boolean delRedisCollection(StringRedisTemplate redisTemplate, Collection<String> keyCollection) {
        if (keyCollection == null || keyCollection.size() == 0) {
            log.error("delRedisCollection error,keyCollection is null or empty!");
            return false;
        }
        try {
            redisTemplate.delete(keyCollection);
            return true;
        } catch (Exception e) {
            log.error("R_ValueRedisMapper delRedisCollection ERROR:", e);
            log.error("Data:" + keyCollection);
            throw e;
        }
    }

    /**
     * 获取redis中的缓存，不更新过期时间
     *
     * @param redisTemplate
     * @param key
     * @return
     */
    public static Integer getRedisInteger(StringRedisTemplate redisTemplate, String key) {
        Integer result = 0;
        if (StringUtils.isBlank(key)) {
            return null;
        }
        try {
            String strValue = redisTemplate.opsForValue().get(key);
            if (!StringUtils.isBlank(strValue)) {
                result = Integer.valueOf(strValue);
            }

        } catch (Exception e) {
            log.error("R_ValueRedisMapper getRedisString ERROR:", e);
            log.error("Data:" + key);
            throw e;
        }
        return result;
    }
}
